

package com.playmodule.vr.projections;

public class HalfSphereProjection extends Projection {
    private SphereProjectionSettings mSettings;

    public HalfSphereProjection(int formatMode, SphereProjectionSettings settings) {
        mSettings = settings;
        setupProjection(formatMode);
    }

    protected void generateMono() {
        generateSphereMono(this.mSettings.stacks, this.mSettings.slices, this.mSettings.width, this.mSettings.height, this.mSettings.depth, 64.0F);
    }

    protected void generateSideBySide() {
        generateSphereSideBySide(this.mSettings.stacks, this.mSettings.slices, this.mSettings.width, this.mSettings.height, this.mSettings.depth, 64.0F);

    }

    protected void generateOverUnder() {
        generateSphereOverUnder(this.mSettings.stacks, this.mSettings.slices, this.mSettings.width, this.mSettings.height, this.mSettings.depth, 64.0F);
    }

    private void generateSphereMono(int stacks, int slices, float width, float height, float depth, float radius) {
        int nVertices = (stacks + 1) * (slices + 1);
        float[] vertices = new float[(nVertices * 3)];
        short[] indices = new short[(nVertices * 6)];
        float[] uv = new float[(nVertices * 2)];
        int verticeIndex = 0;
        int uvIndex = 0;
        int indiceIndex = 0;
        for (int stack = 0; stack <= stacks; stack++) {
            double phi = (Math.PI / 2 - (((double) stack * Math.PI) / (double) stacks));
            double y = ((double) radius * Math.sin(phi)) * (double) height;
            double scale = (double) -radius * Math.cos(phi);
            for (int slice = 0x0; slice <= slices; slice++) {
                double theta = Math.PI / 2 - ((double) (slice) * Math.PI) / (double) slices;
                double x = (Math.sin(theta) * scale) * (double) width;
                double z = (Math.cos(theta) * scale) * (double) depth;
                vertices[(verticeIndex++)] = (float) -x;
                vertices[(verticeIndex++)] = (float) y;
                vertices[(verticeIndex++)] = (float) z;
                uv[(uvIndex++)] = 1 - ((float) slice / (float) slices);
                uv[(uvIndex++)] = 1 - (float) stack / (float) stacks;
            }
        }
        for (int stack = 0; stack < stacks; stack++) {
            int top = (stack + 0) * (slices + 1);
            int bot = (stack + 1) * (slices + 1);
            for (int slice = 0; slice < slices; slice++) {
                indices[(indiceIndex++)] = (short) (top + slice);
                indices[(indiceIndex++)] = (short) (bot + slice);
                indices[(indiceIndex++)] = (short) ((top + slice) + 1);
                indices[(indiceIndex++)] = (short) ((top + slice) + 1);
                indices[(indiceIndex++)] = (short) (bot + slice);
                indices[(indiceIndex++)] = (short) ((bot + slice) + 1);
            }
        }
        mVertices = vertices;
        mIndices = indices;
        mUV = uv;
    }

    private void generateSphereSideBySide(int stacks, int slices, float width, float height, float depth, float radius) {
        int nVertices = (stacks + 0x1) * (slices + 0x1);
        float[] vertices = new float[((nVertices * 0x3) * 0x2)];
        short[] indices = new short[((nVertices * 0x6) * 0x2)];
        float[] uv = new float[((nVertices * 0x2) * 0x2)];
        int verticeIndex = 0x0;
        int uvIndex = 0x0;
        int indiceIndex = 0x0;
        for (int stack = 0; stack <= stacks; stack++) {
            double phi = Math.PI / 2 - (((double) stack * Math.PI) / (double) stacks);
            double y = ((double) radius * Math.sin(phi)) * (double) height;
            double scale = (double) -radius * Math.cos(phi);
            for (int slice = 0; slice <= slices; slice++) {
                double theta = Math.PI / 2 - ((double) (slice) * Math.PI) / (double) slices;
                double x = (Math.sin(theta) * scale) * (double) width;
                double z = (Math.cos(theta) * scale) * (double) depth;
                vertices[(verticeIndex++)] = -(float) x / 2 + 65536.0f;
                vertices[(verticeIndex++)] = (float) y;
                vertices[(verticeIndex++)] = (float) z;
                uv[(uvIndex++)] = 1.0f - ((float) slice / (float) slices) / 2.0f;
                uv[(uvIndex++)] = 1.0f - ((float) stack / (float) stacks);
            }
        }
        for (int stack = 0; stack <= stacks; stack++) {
            double phi = Math.PI / 2 - (((double) stack * Math.PI) / (double) stacks);
            double y = ((double) radius * Math.sin(phi)) * (double) height;
            double scale = (double) -radius * Math.cos(phi);
            for (int slice = 0; slice <= slices; slice++) {
                double theta = Math.PI / 2 - slice * Math.PI / slices;
                double x = (Math.sin(theta) * scale) * (double) width;
                double z = (Math.cos(theta) * scale) * (double) depth;
                vertices[(verticeIndex++)] = -(float) x / 2 - 65536.0f;
                vertices[(verticeIndex++)] = (float) y;
                vertices[(verticeIndex++)] = (float) z;
                uv[(uvIndex++)] = 0.5f - ((float) slice / (float) slices) / 2.0f;
                uv[(uvIndex++)] = (1.0f - ((float) stack / (float) stacks));
            }
        }
        for (int stack = 0; stack <= stacks; stack++) {
            int top = (stack + 0) * (slices + 1);
            int bot = (stack + 1) * (slices + 1);
            for (int slice = 0; slice < slices; slice++) {
                indices[(indiceIndex++)] = (short) (top + slice);
                indices[(indiceIndex++)] = (short) (bot + slice);
                indices[(indiceIndex++)] = (short) ((top + slice) + 1);
                indices[(indiceIndex++)] = (short) ((top + slice) + 1);
                indices[(indiceIndex++)] = (short) (bot + slice);
                indices[(indiceIndex++)] = (short) ((bot + slice) + 1);
            }
        }
        for (int stack = stacks + 1; stack <= stacks * 2; stack++) {
            int top = (stack + 0) * (slices + 1);
            int bot = (stack + 1) * (slices + 1);
            for (int slice = 0; slice < slices; slice++) {
                indices[(indiceIndex++)] = (short) (top + slice);
                indices[(indiceIndex++)] = (short) (bot + slice);
                indices[(indiceIndex++)] = (short) ((top + slice) + 1);
                indices[(indiceIndex++)] = (short) ((top + slice) + 1);
                indices[(indiceIndex++)] = (short) (bot + slice);
                indices[(indiceIndex++)] = (short) ((bot + slice) + 1);
            }
        }
        mVertices = vertices;
        mIndices = indices;
        mUV = uv;
    }

    private void generateSphereOverUnder(int stacks, int slices, float width, float height, float depth, float radius) {
        int nVertices = (stacks + 0x1) * (slices + 0x1);
        float[] vertices = new float[((nVertices * 0x3) * 0x2)];
        short[] indices = new short[((nVertices * 0x6) * 0x2)];
        float[] uv = new float[((nVertices * 0x2) * 0x2)];
        int verticeIndex = 0x0;
        int uvIndex = 0x0;
        int indiceIndex = 0x0;
        for (int stack = 0; stack <= stacks; stack++) {
            double phi = Math.PI / 2 - (((double) stack * Math.PI) / (double) stacks);
            double y = ((double) radius * Math.sin(phi)) * (double) height;
            double scale = (double) -radius * Math.cos(phi);
            for (int slice = 0; slice <= slices; slice++) {
                double theta = Math.PI / 2 - slice * Math.PI / slices;
                double x = (Math.sin(theta) * scale) * (double) width;
                double z = (Math.cos(theta) * scale) * (double) depth;
                vertices[(verticeIndex++)] = -(float) x / 2 + 65536.0f;
                vertices[(verticeIndex++)] = (float) y;
                vertices[(verticeIndex++)] = (float) z;
                uv[(uvIndex++)] = 1.0f - (float) slice / slices;
                uv[(uvIndex++)] = 1.0f - (float) stack / stacks / 2.0f;
            }
        }
        for (int stack = 0; stack <= stacks; stack++) {
            double phi = Math.PI / 2 - (((double) stack * Math.PI) / (double) stacks);
            double y = ((double) radius * Math.sin(phi)) * (double) height;
            double scale = (double) -radius * Math.cos(phi);
            for (int slice = 0; slice <= slices; slice++) {
                double theta = Math.PI / 2 - slice * Math.PI / slices;
                double x = (Math.sin(theta) * scale) * (double) width;
                double z = (Math.cos(theta) * scale) * (double) depth;
                vertices[(verticeIndex++)] = -(float) x / 2 - 65536.0f;
                vertices[(verticeIndex++)] = (float) y;
                vertices[(verticeIndex++)] = (float) z;
                uv[(uvIndex++)] = 1.0f - (float) slice / slices;
                uv[(uvIndex++)] = 0.5f - (float) stack / stacks / 2.0f;
            }
        }
        for (int stack = 0; stack <= stacks; stack++) {
            int top = (stack + 0) * (slices + 1);
            int bot = (stack + 1) * (slices + 1);
            for (int slice = 0; slice < slices; slice++) {
                indices[(indiceIndex++)] = (short) (top + slice);
                indices[(indiceIndex++)] = (short) (bot + slice);
                indices[(indiceIndex++)] = (short) ((top + slice) + 1);
                indices[(indiceIndex++)] = (short) ((top + slice) + 1);
                indices[(indiceIndex++)] = (short) (bot + slice);
                indices[(indiceIndex++)] = (short) ((bot + slice) + 1);
            }
        }
        for (int stack = stacks + 1; stack <= stacks * 2; stack++) {
            int top = (stack + 0) * (slices + 1);
            int bot = (stack + 1) * (slices + 1);
            for (int slice = 0; slice < slices; slice++) {
                indices[(indiceIndex++)] = (short) (top + slice);
                indices[(indiceIndex++)] = (short) (bot + slice);
                indices[(indiceIndex++)] = (short) ((top + slice) + 1);
                indices[(indiceIndex++)] = (short) ((top + slice) + 1);
                indices[(indiceIndex++)] = (short) (bot + slice);
                indices[(indiceIndex++)] = (short) ((bot + slice) + 1);
            }
        }
        mVertices = vertices;
        mIndices = indices;
        mUV = uv;
    }
}
